package com.zjcode.cdcer.service.impl;

import com.chinatechstar.component.commons.entity.MPage;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.chinatechstar.component.commons.service.BaseService;
import com.chinatechstar.component.commons.supports.PageData;
import com.chinatechstar.component.commons.utils.ExcelUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zjcode.cdcer.config.MConsts.Common;
import com.zjcode.cdcer.mapper.CerDetaildataImportInfoMapper;
import com.zjcode.cdcer.mapper.CerEndoscopicDiagnosisDetailsMapper;
import com.zjcode.cdcer.model.TkmEndoscopeDiagnoseNounInfo;
import com.zjcode.cdcer.model.basic.JsonObj;
import com.zjcode.cdcer.model.CerDetaildataImportInfo;
import com.zjcode.cdcer.model.CerEndoscopicDiagnosisDetails;
import com.zjcode.cdcer.pojo.CerSysteminitImportInfo;
import com.zjcode.cdcer.model.SysDict;
import com.zjcode.cdcer.service.*;
import com.zjcode.cdcer.utils.Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CerDetaildataImportInfoServiceImpl implements CerDetaildataImportInfoService,
                                                           BaseService {

    @Autowired
    private CerDetaildataImportInfoMapper cerDetaildataImportInfoMapper;
    @Autowired
    private CerEndoscopicDiagnosisDetailsMapper endoscopicDiagnosisDetailsMapper;
    @Autowired
    private TkmEndoscopeDiagnoseNounInfoService endoscopeDiagnoseNounInfoService;
    @Autowired
    private CerSysteminitImportInfoService cerSysteminitImportInfoService;
    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private SysUserService sysUserService;

    @Override
    public Map<String, Object> listAllTableData(PageData pageData) {
        String userId = (String) pageData.get("user");
        String extFlag = sysUserService.findUserExtFlag(userId);
        pageData.put("extFlag", extFlag);

        // 读取区域信息
        pageData = Utils.transitionRegionInfo(pageData);

        MPage mPage = getPageInfo(pageData);

        //拿到字典数据集合
        List<SysDict> allCerDicts = sysDictService.findAllCerDicts();
        Map<String, List<SysDict>> dictList = allCerDicts
            .stream()
            .collect(Collectors.groupingBy(SysDict::getDictType));

        //设置获取分页数据map
        Page<Object> page = PageHelper.startPage(mPage.getCurrentPage(), mPage.getPageSize());
        List<LinkedHashMap<String, Object>> mapList = cerDetaildataImportInfoMapper.listAllTableData(
            pageData);

        //设置返回数据map
        dictList
            .entrySet()
            .parallelStream()
            .forEach(entry -> {
                // key
                String key = entry.getKey();
                if (key.equals("xb_code")) {
                    key = "sex";
                }
                List<SysDict> dicts = entry.getValue();
                String finalKey = key;
                mapList
                    .stream()
                    .forEach(map -> {
                        Object o = map.get(finalKey);
                        if (o != null) {
                            Optional<SysDict> first = dicts
                                .stream()
                                .filter(sysDict -> sysDict
                                    .getDictValue()
                                    .equals(o.toString()))
                                .findFirst();
                            first.ifPresent(sysDict -> {
                                map.put(finalKey, sysDict.getDictName());
                            });
                        }
                    });
            });

        // 还原内镜诊断
        mapList
            .parallelStream()
            .forEach(map -> {
                String njzd = (String) map.get("njzd");
                List<String> ids = Arrays.asList(njzd.split(","));
                List<TkmEndoscopeDiagnoseNounInfo> nounInfos = endoscopeDiagnoseNounInfoService.selectByNounIds(
                    ids);
                if (nounInfos != null) {
                    map.put("njzd",
                            nounInfos
                                .stream()
                                .map(each -> each.getName())
                                .collect(Collectors.joining(",")));
                } else {
                    map.put("njzd", "");
                }
            });

        // 身份证, 给身份证加上掩码
        mapList
            .parallelStream()
            .forEach(each -> {
                String sfz = (String) each.get("sfz");
                if (sfz != null) {
                    each.put("sfz", sfz.substring(0, 6) + "********" + sfz.substring(14));
                }
            });

        return PaginationBuilder.buildResult(mapList,
                                             page.getTotal(),
                                             mPage.getCurrentPage(),
                                             mPage.getPageSize());
    }

    @Override
    public List<LinkedHashMap<String, Object>> queryAllExportData(PageData pageData) {
        String userId = (String) pageData.get("user");
        String extFlag = sysUserService.findUserExtFlag(userId);
        pageData.put("extFlag", extFlag);

        // 获取ids
        String ids = String.valueOf(pageData.get("ids"));
        List<String> idList = new ArrayList<>();
        if (!StringUtils.isEmpty(userId)) {
            idList.addAll(Arrays.asList(ids.split("\\|")));
        }
        pageData.put("idList", idList);

        //拿到字典数据集合
        List<SysDict> allCerDicts = sysDictService.findAllCerDicts();
        Map<String, List<SysDict>> dictList = allCerDicts
            .stream()
            .collect(Collectors.groupingBy(SysDict::getDictType));

        //获取详细列表数据
        List<LinkedHashMap<String, Object>> mapList = cerDetaildataImportInfoMapper.queryAllExportData(
            pageData);

        //设置返回数据map
        dictList
            .entrySet()
            .parallelStream()
            .forEach(entry -> {
                // key
                String key = entry.getKey();
                if (key.equals("xb_code")) {
                    key = "sex";
                }
                List<SysDict> dicts = entry.getValue();
                String finalKey = key;
                mapList
                    .stream()
                    .forEach(map -> {
                        Object o = map.get(finalKey);
                        if (o != null) {
                            Optional<SysDict> first = dicts
                                .stream()
                                .filter(sysDict -> sysDict
                                    .getDictValue()
                                    .equals(o.toString()))
                                .findFirst();
                            first.ifPresent(sysDict -> {
                                map.put(finalKey, sysDict.getDictName());
                            });
                        }
                    });
            });

        return mapList;
    }

    @Override
    public JsonObj batchDeletion(PageData pageData) {
        pageData.put("status", 1);
        String data = String.valueOf(pageData.get("data"));
        String[] ids = data.split("\\|");
        if (ids.length > 0) {
            pageData.put("data", ids);
            cerDetaildataImportInfoMapper.batchDeletion(pageData);
            return JsonObj.success("删除成功！");
        }
        return JsonObj.error("已取消！");
    }

    @Override
    public JsonObj oneClickDelete(PageData pageData) {
        pageData.put("status", 1);
        cerDetaildataImportInfoMapper.oneClickDelete(pageData);
        return JsonObj.success("已删除！");
    }

    @Override
    public List<CerDetaildataImportInfo> getAllNoErrorData(PageData pageData) {
        // 查询没有错误的数据,没有被标记超时的数据,没有上报的数据
        List<CerDetaildataImportInfo> data = cerDetaildataImportInfoMapper.getAllNoErrorData(
            pageData);
        if (CollectionUtils.isEmpty(data)) {
            data = new ArrayList<>();
        }
        return data;
    }

    @Override
    public void updateCerDetaildataImportOfficeInfoStatus(PageData pageData) {
        // 标记删除
        pageData.put("deleted", 1);
        // 标记数据无错
        pageData.put("isHaveError", 0);
        // 没有超时上报
        pageData.put("is_uplpad_timeout", 0);
        // 是否上报正式库
        pageData.put("is_uploaded", 1);
        cerDetaildataImportInfoMapper.updateCerDetaildataImportInfoStatus(pageData);
    }

    @Override
    public int deleteById(String id) {
        return cerDetaildataImportInfoMapper.deleteById(id);
    }

    @Override
    public CerDetaildataImportInfo findDataById(String id) {
        return cerDetaildataImportInfoMapper.findDataById(id);
    }

    /**
     * 批量插入
     */
    @Override
    public int batchInsert(List<CerSysteminitImportInfo> list) {
        // 数据类型转换 CerDetaildataImportInfo
        List<CerDetaildataImportInfo> importInfos = list
            .stream()
            .map(source -> {

                // 查看当前记录是否有内镜详情
                List<CerEndoscopicDiagnosisDetails> details = endoscopicDiagnosisDetailsMapper.findByParentId(
                    source.getId());

                CerDetaildataImportInfo target = new CerDetaildataImportInfo();
                BeanUtils.copyProperties(source, target);
                // 年龄
                target.setAge(Integer.parseInt(source.getAge()));
                //

                // 内镜报告单是否上传
                target.setNjReportStatus(StringUtils.isEmpty(source.getReportFileUrl()) ? 0 : 1);
                // 病理报告单是否上传
                target.setBlReportStatus(StringUtils.isEmpty(source.getBlReportFileUrl()) ? 0 : 1);
                // 获取extflag2的值
                String extFlag2 = target.getExtFlag2();
                if (StringUtils.equals("0|0|0", extFlag2)) {
                    extFlag2 = getExtFlag2(target);
                    if (CollectionUtils.isEmpty(details)) {
                        target.setExtFlag2(extFlag2);
                    }
                }

                // 获取错误信息
                List<String> errors = validateDetailDataImportInfoData(target, details);
                if (errors.size() > 0) {
                    target.setIsHaveError(1);
                    target.setErrorMessage(String.join("|", errors));
                } else {
                    target.setIsHaveError(0);
                    target.setErrorMessage("");
                }

                log.info(errors.toString());

                return target;
            })
            .collect(Collectors.toList());

        //log.info(importInfos.size() + "");

        return cerDetaildataImportInfoMapper.insertList(importInfos);

    }

    @Override
    public int updateRecord(CerDetaildataImportInfo detaildataImportInfo) {
        return cerDetaildataImportInfoMapper.updateRecord(detaildataImportInfo);
    }

    @Override
    public List<CerDetaildataImportInfo> findAllByDateTimeRange(String start, String end) {
        return cerDetaildataImportInfoMapper.selectAllByInsertDatetimeBetweenOrEqualTo(start, end);
    }

    @Override
    public List<CerDetaildataImportInfo> selectByNjNum(String code,String extFlag) {
        return cerDetaildataImportInfoMapper.selectByNjNum(code,extFlag);
    }

    @Override
    public List<CerDetaildataImportInfo> selectByBlNum(String code,String extFlag) {
        return cerDetaildataImportInfoMapper.selectByBlNum(code,extFlag);
    }

    @Override
    public List<CerDetaildataImportInfo> selectByNameAndNjzlTime(String name,
                                                                 String njzlTime,
                                                                 String extFlag) {
        return cerDetaildataImportInfoMapper.selectByNameAndNjzlTime(name, njzlTime, extFlag);
    }

    @Override
    public List<CerDetaildataImportInfo> selectByNameAndBlbgTime(String name,
                                                                 String blbgTime,
                                                                 String extFlag) {
        return cerDetaildataImportInfoMapper.selectByNameAndBlbgTime(name, blbgTime, extFlag);
    }

    @Override
    public void exportDetailForGJMode(PageData pageData, HttpServletResponse response) {
        String userId = (String) pageData.get("user");
        Object idsData = pageData.get("ids");
        String extFlag = sysUserService.findUserExtFlag(userId);
        pageData.put("extFlag", extFlag);
        List<String> ids = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(idsData)) {
            ids = Arrays.asList(String.valueOf(idsData).split("\\|"));
        }
        List<LinkedHashMap<String, Object>> list = cerDetaildataImportInfoMapper.selectDetailForGJMode(ids,idsData,pageData);
        cerSysteminitImportInfoService.setCommonExportData(list);
        // 组装表头
        List<String> headList = Arrays.asList("不合格原因",
                "省份",
                "城市",
                "区县",
                "机构名称",
                "姓名",
                "性别",
                "年龄",
                "身份证号",
                "地址",
                "联系电话",
                "门诊号",
                "住院号",
                "内镜诊疗日期",
                "对象来源",
                "内镜号",
                "是否无痛",
                "染色类别",
                "图片数量",
                "是否活检",
                "Hp",
                "Hp检测方法",
                "内镜诊断",
                "内镜诊断医师",
                "内镜审核医师",
                "病理号",
                "病理诊断",
                "食管病理诊断代码",
                "贲门病理诊断代码",
                "胃病理诊断代码",
                "十二指肠病理诊断代码",
                "病理诊断医师",
                "病理审核医师",
                "病理报告日期");
        try {
            // 导出
            ExcelUtils.exportExcel(headList, list, "详情数据导出（国家平台导出模板格式）", response);
        } catch (Exception e) {
            log.info("导入失败，原因：", e);
        }
    }

    /**
     * 获取Extflag2的值
     *
     * @param target
     * @return
     */
    private String getExtFlag2(CerDetaildataImportInfo target) {
        List<Integer> flags = new ArrayList<>();
        // 获取食管病理诊断代码
        String sgblCode = target.getSgblCode();
        flags.add(getFlagByCode(sgblCode));
        // 获取贲门病理诊断代码
        String bmblCode = target.getBmblCode();
        flags.add(getFlagByCode(bmblCode));
        // 获取胃病理诊断代码
        String wblCode = target.getWblCode();
        flags.add(getFlagByCode(wblCode));
        String extFlag2 = flags
            .stream()
            .map(String::valueOf)
            .collect(Collectors.joining(Common.DELIMITER_CHARACTER));
        return extFlag2;
    }

    /**
     * 验证并获取详情数据上报的错误信息
     *
     * @param source
     * @param details
     * @return
     */
    private List<String> validateDetailDataImportInfoData(CerDetaildataImportInfo info,
                                                          List<CerEndoscopicDiagnosisDetails> details) {
        List<String> errors = new ArrayList<>();
        // 检测内镜报告单
        if (info.getNjReportStatus() == 0) {
            errors.add("内镜报告单必须上传");
        }
        String riskReportId = info.getRiskReportId();
        if (StringUtils.isEmpty(riskReportId)) {
            errors.add("风险因素自测表未填写");
        }
        // 检测病理报告单
        boolean needUploadBlReport = false;
        if (CollectionUtils.isEmpty(details)) {
            errors.add("请填正确填写内镜详情");
        } else {
            // 查找详情中,是否活检字段的值
            boolean hj = false;
            for (CerEndoscopicDiagnosisDetails detail : details) {
                Integer isHj = detail.getIsHj();
                if (isHj == 1) {
                    hj = true;
                    break;
                }
            }
            // 当详情中,是否活检字段的值为true时,则需要上传病理报告单
            if (hj) {
                needUploadBlReport = true;
            }
        }
        if (needUploadBlReport && info.getBlReportStatus() == 0) {
            errors.add("病理报告单必须上传");
        }
        // 检查内镜详情是否有填写过
        String extFlag2 = info.getExtFlag2();
        if (!"0|0|0".equals(extFlag2) && details.size() == 0) {
            String[] strings = extFlag2.split("\\|");
            List<String> tmp = new ArrayList<>();
            if (strings.length == 3) {
                if (strings[0].equals("1")) {
                    tmp.add("食管");
                }
                if (strings[1].equals("1")) {
                    tmp.add("贲门");
                }
                if (strings[2].equals("1")) {
                    tmp.add("胃");
                }
            }
            errors.add(tmp
                           .stream()
                           .collect(Collectors.joining(Common.DELIMITER_CHARACTER))
                           + "详情添加完整");
        }
        return errors;
    }

    private int getFlagByCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return 0;
        }
        long count = Common.DIAGNOSTIC_CODE_LIST
            .stream()
            .filter(c -> {
                return c.equals(code);
            })
            .count();
        if (count > 0) {
            return 1;
        }
        return 0;
    }
}
